<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>G6 思维导图 - Mock 示例</title>
    <script src="https://unpkg.com/@antv/g6@4.8.22/dist/g6.min.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: sans-serif;
        }

        #container {
            width: 100vw;
            height: 100vh;
            position: relative;
            overflow: hidden;
        }

        /* 其他样式... */
    </style>
</head>

<body>
    <div id="container" style="width: 100vw;height: 100vh;">
    </div>
</body>
<script>

    const Util = G6.Util;
    const data = {
        nodes: [
            {
                id: 'node1',
                x: 100,
                y: 100,
                type: 'circle-animate',
                size: 20,
                label: 'Scale Animation',
                labelCfg: {
                    position: 'top',
                },
            },
            {
                id: 'node2',
                x: 300,
                y: 200,
                type: 'background-animate',
                color: '#40a9ff',
                size: 20,
                label: 'Background Animation',
                labelCfg: {
                    position: 'left',
                    offset: 10,
                },
            },
            {
                id: 'node3',
                x: 400,
                y: 100,
                size: [40, 40],
                type: 'inner-animate',
                img:
                    '',
                label: 'Image Rotate',
                labelCfg: {
                    position: 'right',
                },
            },
            {
                id: 'node4',
                x: 300,
                y: 300,
                type: 'rect',
                label: 'No Animation',
                labelCfg: {
                    position: 'bottom',
                },
            },
        ],
        edges: [
            {
                source: 'node1',
                target: 'node2',
            },
            {
                source: 'node3',
                target: 'node2',
            },
            {
                source: 'node2',
                target: 'node4',
            },
        ],
    };

    // Scale Animation
    G6.registerNode(
        'circle-animate',
        {
            afterDraw(cfg, group) {
                const shape = group.get('children')[0];
                shape.animate(
                    (ratio) => {
                        const diff = ratio <= 0.5 ? ratio * 10 : (1 - ratio) * 10;
                        return {
                            r: cfg.size / 2 + diff,
                        };
                    },
                    {
                        repeat: true,
                        duration: 3000,
                        easing: 'easeCubic',
                    },
                );
            },
        },
        'circle',
    );

    // Background Animation
    G6.registerNode(
        'background-animate',
        {
            afterDraw(cfg, group) {
                const r = cfg.size / 2;
                const back1 = group.addShape('circle', {
                    zIndex: -3,
                    attrs: {
                        x: 0,
                        y: 0,
                        r,
                        fill: cfg.color,
                        opacity: 0.6,
                    },
                    // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
                    name: 'back1-shape',
                });
                const back2 = group.addShape('circle', {
                    zIndex: -2,
                    attrs: {
                        x: 0,
                        y: 0,
                        r,
                        fill: cfg.color,
                        opacity: 0.6,
                    },
                    // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
                    name: 'back2-shape',
                });
                const back3 = group.addShape('circle', {
                    zIndex: -1,
                    attrs: {
                        x: 0,
                        y: 0,
                        r,
                        fill: cfg.color,
                        opacity: 0.6,
                    },
                    // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
                    name: 'back3-shape',
                });
                group.sort(); // Sort according to the zIndex
                back1.animate(
                    {
                        // Magnifying and disappearing
                        r: r + 10,
                        opacity: 0.1,
                    },
                    {
                        duration: 3000,
                        easing: 'easeCubic',
                        delay: 0,
                        repeat: true, // repeat
                    },
                ); // no delay
                back2.animate(
                    {
                        // Magnifying and disappearing
                        r: r + 10,
                        opacity: 0.1,
                    },
                    {
                        duration: 3000,
                        easing: 'easeCubic',
                        delay: 1000,
                        repeat: true, // repeat
                    },
                ); // 1s delay
                back3.animate(
                    {
                        // Magnifying and disappearing
                        r: r + 10,
                        opacity: 0.1,
                    },
                    {
                        duration: 3000,
                        easing: 'easeCubic',
                        delay: 2000,
                        repeat: true, // repeat
                    },
                ); // 3s delay
            },
        },
        'circle',
    );

    // Image animation
    G6.registerNode(
        'inner-animate',
        {
            afterDraw(cfg, group) {
                const size = cfg.size;
                const width = size[0] - 12;
                const height = size[1] - 12;
                const image = group.addShape('image', {
                    attrs: {
                        x: -width / 2,
                        y: -height / 2,
                        width,
                        height,
                        img: cfg.img,
                    },
                    // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
                    name: 'image-shape',
                });
                image.animate(
                    (ratio) => {
                        const toMatrix = Util.transform(
                            [1, 0, 0, 0, 1, 0, 0, 0, 1],
                            [['r', ratio * Math.PI * 2]],
                        );
                        return {
                            matrix: toMatrix,
                        };
                    },
                    {
                        repeat: true,
                        duration: 3000,
                        easing: 'easeCubic',
                    },
                );
            },
        },
        'rect',
    );

    const container = document.getElementById('container');
    const width = container.scrollWidth;
    const height = container.scrollHeight || 500;
    const graph = new G6.Graph({
        container: 'container',
        width,
        height,
        defaultNode: {
            style: {
                fill: '#DEE9FF',
                stroke: '#5B8FF9',
            },
        },
        defaultEdge: {
            style: {
                lineWidth: 1,
                stroke: '#b5b5b5',
            },
        },
    });
    graph.data(data);
    graph.render();

    if (typeof window !== 'undefined')
        window.onresize = () => {
            if (!graph || graph.get('destroyed')) return;
            if (!container || !container.scrollWidth || !container.scrollHeight) return;
            graph.changeSize(container.scrollWidth, container.scrollHeight);
        };
</script>

</html>